<template>
  <div>
    <Card slot="demo">
      <h2 slot="title">1. 组件继承，重载slot</h2>
      <p>1. 依靠 <code>render-dom</code> 工具组件代理渲染</p>
      <p>2. 根据 <code>slotName</code> 进行特殊处理</p>
      <p>3. 绑定slot <code>:slot="slotName"</code> 进行特殊处理</p>
      <Code lang="js">{{code.slotOverload}}</Code>
    </Card>
    <Card slot="demo">
      <h2 slot="title">2. 迭代渲染slot组件</h2>
      <h3>render-dom 工具组件代理渲染</h3>
      <Code>{{code.slotIterator}}</Code>
    </Card>
    <Card slot="demo">
      <h2 slot="title">3. 组件继承，传递属性</h2>
      <p>v-bind=$attrs 绑定非props选项</p>
      <p>v-on=$listeners 绑定事件</p>
      <Code>{{code.componentExtend}}</Code>
    </Card>
    <Card slot="demo">
      <h2 slot="title">4. Vue组件 vs. 原生dom</h2>
      <h3>a. 绑定事件 </h3>
      <ul style="list-style-position: inside">
        <li> Vue组件 -- @click.native="onClick"</li>
        <li> 原生dom -- @click="onClick"</li>
      </ul>
      <h3>b. refs 获取width,height等dom属性 </h3>
      <ul style="list-style-position: inside">
        <li> Vue组件 -- $refs.refName.$el.offsetWidth</li>
        <li> 原生dom -- $refs.refName.offsetWidth</li>
      </ul>
      <Code>{{code.componentAndDom}}</Code>
    </Card>
    <Card slot="demo">
      <h2 slot="title">5. Vuex 小贴士</h2>
      <ul style="list-style-position: inside">
        <li> namespaced -- 开启后使用命名空间</li>
        <li> mutations -- 操作state</li>
        <li> getters -- 类比computed属性，可以操作state和其他getters</li>
        <li> actions -- 可以直接操作state，引用getters，也可以通过commit提交mutation，但是只能额外传递一个参数</li>
      </ul>
      <Code lang="js">{{code.vuexTips}}</Code>
    </Card>
  </div>
</template>

<script>
import Code from '_c/code'
export default {
  name: 'summary',
  components: { Code },
  data: () => {
    return {
      code: {
        slotOverload: `
// render-dom.js
export default {
  name: 'RenderDom',
  functional: true,
  props: {
    render: Function
  },
  render: (h, ctx) => {
    return ctx.props.render(h)
  }
}
// component.vue
<template v-for="(slots, slotsName) in $slots">
  <template v-if="slotsName !== 'footer'">
    <render-dom v-for="(render, index) in slots"
                :key="\`d_card_\${slotsName}_\${index}\`"
                :render="() => render"
                :slot="slotsName">
    </render-dom>
  </template>
</template>
        `,
        slotIterator: `
// componentA.vue
<div class="list-item" v-for="(item, index) in list" :key="\`list_\${index}\`">
  <slot name="slotName" :scoped-attr.camel="item">{{ item }}</slot>
</div>

// wrapper.vue
<componentA :list="list">
  <Alert class="item" slot="slotName" slot-scope="props">{{ props.scopedAttr.name }}</Alert>
</componentA>
        `,
        componentExtend: `
// parent.vue
<parent :bind="props"></parent>
// extend.vue
<extend
  v-bind="$attrs"
  v-on="$listeners">
</extend>
        `,
        componentAndDom: `
<template>
  <div>
    <Tag ref="tag" @click.native="onClickTag('tag')">Click on Tag</Tag>
    <div ref="div" @click="onClick('div')">Click on div</div>
  </div>
</template>
export default {
  name: 'app',
  methods: {
    onClick (name) {
      console.log('click on ' + name)
    }
  },
  mounted() {
    this.$nextTick(() => {
      // 对于组件引用先用$el获取真实dom
      let tagHeight = this.$refs.tag.$el.offsetHeight
      // 对于dom引用直接操作即可
      let divHeight = this.$refs.div.offsetHeight
      console.log(tagHeight, divHeight)
    })
  }
}
`,
        vuexTips: `
export default {
  namespaced: true,
  state: {
    user: {
      balance: 100
    },
    goods: {},
    cart: []
  },
  getters: {
    goodsList: state => Object.values(state.goods),
    cartTotalPrice: state => {
      let total = 0
      for (let item of state.cart) {
        total += state.goods[item.id].price * item.num
      }
      return total
    },
    // use getters
    cartTotalPriceEx: (state, getters) => {
      return getters.cartTotalPrice.toFixed(2)
    }
  },
  mutations: {
    setGoods (state, goods) {
      state.goods = goods
    },
    // can pass only one argument
    addCart (state, { id, num, details }) {
      state.cart.push({
        id,
        num,
        details
      })
    },
    updateCart (state, data) {
      let { idx, num } = data
      state.cart[idx].num += num
      if (state.cart[idx].num <= 0) {
        // delete an item of Array state
        state.cart.splice(idx, 1)
      }
    },
    removeCart (state) {
      state.cart = []
    }
  },
  actions: {
    initGoodsList ({ commit, state }, filter) {
      return new Promise((resolve, reject) => {
        getGoodsList(filter).then(res => {
          commit('setGoods', res.data.data)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },
    // use both state and getters
    payCart ({ commit, state, getters }) {
      return new Promise((resolve, reject) => {
        if (getters.cartTotalPrice > state.user.balance) {
          reject(new Error('no enough balance'))
        } else {
          // update with committing a mutation
          commit('updateUserBalance', -getters.cartTotalPrice)
          // update state directly
          state.cart = []
          resolve()
        }
      })
    }
  }
}
        `
      }
    }
  }
}
</script>

<style scoped>
  .ivu-card {
    margin: 15px 0;
  }
</style>
